package util;

import java.util.ArrayList;
import java.util.Random;

public class WineRecommender {	
	private String mildCheeses = "cottage,mozzarella,chevre,feta,cream cheese,munster,parmesan,american cheese,colby";
	private String strongCheeses = "blue,cheddar,smoked,swiss,monterey jack";
	private String soups = "soup,broth";
	private String mildSeafood = "catfish,tilapia,whitefish,flounder,haddock,halibut,snapper,scallop";
	private String richSeafood = "tuna,salmon,trout,crab,lobster,oyster,calimari,clam,shrimp,escargot";
	private String salads = "salad,greens,lettuce,cabbage,spinach";
	private String egg = "egg";
	private String lightPastaAndGrains = "spaghettini,spaghetti squash,farfalle,orecchiette,penne,orzo,rotini,elbow,rice";
	private String richPasta = "spaghetti,fedelini,vermicelli,vermicelloni,pici,fettuccine,lasagna,fusilli,gemelli,manicotti,ziti,agnolotii,pierogi,pelmini,raviolli,tortellini,gnocchi";
	private String gameBirds = "pheasant,chukar,grouse,goose,hen,dove";
	private String pizza = "dough,flour,yeast,pizza";
	private String barbecue = "barbecue";
	private String burger = "hamburger,bun";
	private String beef = "beef,hamburger,steak,ribs";
	private String stews = "potato,carrots,stewing";
	private String fruit = "fruit,raspberry,blueberry,kiwi,strawberry,banana,mango,mellon,apple";
	private String commonHerbs = "rosemary,caraway seeds,coriander,cumin,curry powder,dill,garlic,sage,fennel,savory,thyme,chili powder,cayenne pepper,paprika";
	private String tomatoSauce = "tomato sauce,tomato paste,tomato puree";
	private String cheeseSauce = "butter,milk";
	private String fruitCake = "cake,"+fruit;
	private String creams = "cream";
	private String custard = "custard";
	private String souffles = "egg white";
	private String nuts = "peanut,almond,walnut,acorn,pistachio,cashew";
	private String vegtables = "lettuce,cabbage,green bean,beet,corn,squash,zuchinni,spinach";
	private String spicy = "pepper,chili,curry,cajun,chipolte,red pepper,harissa,jerk,creole,gigner,cayenne";
	
	
	private ArrayList<WineCategory> categories = new ArrayList<WineCategory>();
	
	public ArrayList<Varietal> recommend(String commaSepIngredients){
		ArrayList<WineCategory> topCategories = new ArrayList<WineCategory>();
		int highRank = 0;
		for(WineCategory category : categories){
			int rank = category.rank(commaSepIngredients);
			if(rank == highRank)
				topCategories.add(category);
			else if(rank > highRank){
				highRank = rank;
				topCategories = new ArrayList<WineCategory>();
				topCategories.add(category);
			}
		}
		
		ArrayList<VarietalRanking> allVarietalRankings = new ArrayList<VarietalRanking>();
		for(WineCategory category : topCategories){
			addRankings(allVarietalRankings, category.getVarietalRankings(commaSepIngredients));
		}
		
		return getTopFiveVarietals(allVarietalRankings);
	}
	
	private ArrayList<Varietal> getTopFiveVarietals(ArrayList<VarietalRanking> allVarietalRankings){
		ArrayList<Varietal> topFive = new ArrayList<Varietal>();
		//For now just return the first 5 on the list which will be a slightly skewed result if varietals all
		//have the same rankings.
		
		//Get the all of the top ranked
		int topRank = allVarietalRankings.get(0).getRanking();
		ArrayList<Varietal> allTop = new ArrayList<Varietal>();
		for(VarietalRanking ranking : allVarietalRankings){
			if(ranking.getRanking() == topRank)
				allTop.add(ranking.getVarietal());
			else
				break;
		}
		if(allTop.size() > 5){
			boolean[] seen = new boolean[allTop.size()];
			Random r = new Random();
			int index = r.nextInt(allTop.size());
			seen[index] = true;
			topFive.add(allTop.get(index));
			int count = 1;
			while(count < 6){
				index = r.nextInt(allTop.size());
				if(!seen[index]){
					topFive.add(allTop.get(index));
					seen[index] = true;
					count++;
				}
			}
		}
		else{
			topFive.addAll(allTop);
			int newCount = 5 - allTop.size();
			if(newCount != 0){
				int secondRank = allVarietalRankings.get(allTop.size()).getRanking();
				ArrayList<Varietal> secondBest = new ArrayList<Varietal>();
				for(int i = allTop.size(); i < allVarietalRankings.size(); i++){
					VarietalRanking ranking = allVarietalRankings.get(i);
					if(ranking.getRanking() == secondRank)
						secondBest.add(ranking.getVarietal());
					else
						break;
				}
				
				if( secondBest.size() > newCount){
					boolean[] seen = new boolean[secondBest.size()];
					Random r = new Random();
					int index = r.nextInt(secondBest.size());
					seen[index] = true;
					topFive.add(secondBest.get(index));
					int count = 1;
					while(count < newCount){
						index = r.nextInt(secondBest.size());
						if(!seen[index]){
							topFive.add(secondBest.get(index));
							seen[index] = true;
							count++;
						}
					}
				}
				else{
					for(int i = 0; i < newCount; i++)
						topFive.add(allVarietalRankings.get(allTop.size() + i).getVarietal());
				}
			}
		}
		return topFive;
	}
	
	private void addRankings(ArrayList<VarietalRanking> all, ArrayList<VarietalRanking> categoryRanks){
		if(all.isEmpty())
			all.addAll(categoryRanks);
		else{
			for(VarietalRanking ranking : categoryRanks){
				for(int i = 0; i < all.size(); i++){
					VarietalRanking r = all.get(i);
					if(ranking.compareTo(r) >= 0){
						all.add(i,ranking);
						break;
					}
					else if(i == all.size() - 1){
						all.add(ranking);
						break;
					}
				}
			}
		}
	}
	
	public WineRecommender(){
		String lmwIngredients = "chicken,turkey"+","+mildCheeses+","+soups+","+mildSeafood+","+salads+","+egg+","+lightPastaAndGrains;
		String fwIngredients = "chicken,turkey,duck,pork,veal"+","+richPasta+","+richSeafood+","+gameBirds+","+mildCheeses;
		String lrIngredients = richPasta+","+tomatoSauce+","+cheeseSauce+","+richSeafood+",chicken,turkey,veal,pork,"+fruit+","+barbecue+","+burger+","+pizza+","+mildCheeses;
		String mrIngredients = richPasta+",duck,"+gameBirds+","+commonHerbs+",pork,veal,"+beef+","+stews+","+barbecue+","+burger+","+pizza+","+mildCheeses+","+strongCheeses;
		String frIngredients = tomatoSauce+","+cheeseSauce+",duck,"+gameBirds+","+commonHerbs+",pork,veal,"+beef+","+stews+","+strongCheeses;
		String swIngredients = "chicken,turkey"+","+mildCheeses+","+soups+","+mildSeafood+","+richSeafood+","+salads+","+egg+","+lightPastaAndGrains+","+commonHerbs+","+fruit+",pork,veal";
		String dwIngredients = mildCheeses+","+fruitCake+","+creams+","+custard+","+souffles;
		String drIngredients = "chocolate, coffee,"+nuts;
		
		WineCategory dwCat = new WineCategory(Category.DESERT_WHITE,dwIngredients.split(","));
		String muscat_d = "";
		String riesling_d = "";
		String muscadelle_d = "";
		String viognier_d = "";
		String gewurtztraminer_d = "";
		dwCat.addVarietal(new WineVarietal(Varietal.MUSCAT_DESSERT, muscat_d));
		dwCat.addVarietal(new WineVarietal(Varietal.RIESLING_DESERT, riesling_d));
		dwCat.addVarietal(new WineVarietal(Varietal.MUSCADELLE_DESSERT, muscadelle_d));
		dwCat.addVarietal(new WineVarietal(Varietal.VIOGNIER_DESSERT, viognier_d));
		dwCat.addVarietal(new WineVarietal(Varietal.GEWURTZTRAMINER_DESERT, gewurtztraminer_d));
		categories.add(dwCat);
		
		WineCategory drCat = new WineCategory(Category.DESERT_RED,drIngredients.split(","));
		String hidalgo = "";
		String grenache_d = "";
		String port_blend = "";
		String port = "";
		String pinot_noir_d = "";
		drCat.addVarietal(new WineVarietal(Varietal.HIDALGO_DESERT, hidalgo));
		drCat.addVarietal(new WineVarietal(Varietal.GRENACHE_DESSERT, grenache_d));
		drCat.addVarietal(new WineVarietal(Varietal.PORT_BLEND, port_blend));
		drCat.addVarietal(new WineVarietal(Varietal.PORT, port));
		drCat.addVarietal(new WineVarietal(Varietal.PINOT_NOIR_DESSERT, pinot_noir_d));
		categories.add(drCat);
		
		WineCategory swCat = new WineCategory(Category.SPARKLING,swIngredients.split(","));
		String macabeo = "goat cheese,mayonnaise,mint," + fruit;
		String parellada = "chocolate,goat cheese,caviar,egg,oyster";
		String champagne = "anchovy,apple,currant,blue,caramel,cherry,chestnuts,coffee";
		String prosecco = "calimari," + salads;
		String brachetto = salads + "," + fruit;
		swCat.addVarietal(new WineVarietal(Varietal.MACABEO, macabeo));
		swCat.addVarietal(new WineVarietal(Varietal.PARELLADA, parellada));
		swCat.addVarietal(new WineVarietal(Varietal.CHAMPAGNE, champagne));
		swCat.addVarietal(new WineVarietal(Varietal.PROSECCO, prosecco));
		swCat.addVarietal(new WineVarietal(Varietal.BRACHETTO, brachetto));
		categories.add(swCat);
		
		
		WineCategory lmwCat = new WineCategory(Category.LIGHT_AND_MEDIUM_WHITE,lmwIngredients.split(","));
		String chenin_blanc = fruit + ",soy," + creams;
		String melon_de_bourgogne = "";
		String gewurtztraminer = "soy," + spicy + ",vinegar,lime,lemon";
		String riesling = spicy + "salt,soy,smoke,curry";
		String sauvignon_blanc = "sushi,fried,butter,cream";
		lmwCat.addVarietal(new WineVarietal(Varietal.CHENIN_BLANC, chenin_blanc));
		lmwCat.addVarietal(new WineVarietal(Varietal.MELON_DE_BOURGOGNE, melon_de_bourgogne));
		lmwCat.addVarietal(new WineVarietal(Varietal.GEWURTZTRAMINER, gewurtztraminer));
		lmwCat.addVarietal(new WineVarietal(Varietal.RIESLING, riesling));
		lmwCat.addVarietal(new WineVarietal(Varietal.SAUVIGNON_BLANC, sauvignon_blanc));
		categories.add(lmwCat);
		
		WineCategory fwCat = new WineCategory(Category.FULL_WHITE,fwIngredients.split(","));
		String chardonnay = "mushroom," + fruit + ",saffron";
		String pinot_gris = "salami,a;fredo,parmesan,lemongrass";
		String semillon = "almond,asparagus";
		String viognier = creams + ",chicken,caramel,rice";
		String gruner_veltliner = "cider,dill,rusotto,saffron,horseradish";
		fwCat.addVarietal(new WineVarietal(Varietal.CHARDONNAY, chardonnay));
		fwCat.addVarietal(new WineVarietal(Varietal.PINOT_GRIS, pinot_gris));
		fwCat.addVarietal(new WineVarietal(Varietal.SEMILLON, semillon));
		fwCat.addVarietal(new WineVarietal(Varietal.VIOGNIER, viognier));
		fwCat.addVarietal(new WineVarietal(Varietal.GRUNER_VELTLINER, gruner_veltliner));
		categories.add(fwCat);
		
		
		WineCategory lrCat = new WineCategory(Category.LIGHT_RED,lrIngredients.split(","));
		String ros = tomatoSauce + ",mushroom" + vegtables;
		String cabernet_franc = tomatoSauce + "pepper,wine";
		String gamay = "brie,munster,egg,lettuce,potato";
		String sangiovese = "pancetta,parmesan,bean,marinade";
		String zinfandel = spicy + ",berry, prune," + tomatoSauce;
		lrCat.addVarietal(new WineVarietal(Varietal.ROS, ros));
		lrCat.addVarietal(new WineVarietal(Varietal.CABERNET_FRANC, cabernet_franc));
		lrCat.addVarietal(new WineVarietal(Varietal.GAMAY, gamay));
		lrCat.addVarietal(new WineVarietal(Varietal.SANGIOVESE, sangiovese));
		lrCat.addVarietal(new WineVarietal(Varietal.ZINFANDEL, zinfandel));
		categories.add(lrCat);
		
		WineCategory mrCat = new WineCategory(Category.MEDIUM_RED,mrIngredients.split(","));
		String bordeaux = "potato,bean,gouda";
		String grenache = "pepper,tounge";
		String merlot = "balsamic,soy,hot,pepper,black olive";
		String pinot_noir = "cherry,smoke,bacon,black bean";
		mrCat.addVarietal(new WineVarietal(Varietal.BORDEAUX, bordeaux));
		mrCat.addVarietal(new WineVarietal(Varietal.CABERNET_FRANC, cabernet_franc));
		mrCat.addVarietal(new WineVarietal(Varietal.GRENACHE, grenache));
		mrCat.addVarietal(new WineVarietal(Varietal.MERLOT, merlot));
		mrCat.addVarietal(new WineVarietal(Varietal.PINOT_NOIR, pinot_noir));
		categories.add(mrCat);
		
		WineCategory frCat = new WineCategory(Category.FULL_RED,frIngredients.split(","));
		String syrah  = barbecue + ",olive,chili verde,green pepper";
		String cabernet_sauvignon = "hoison,soy,bolgnese,puttanese";
		String malbec  = tomatoSauce = ",pepper," +barbecue;
		String aglianico = "green peppercorn,olive,vinegar";
		String barbera = "grape,swiss,cabbage,rosemary";
		frCat.addVarietal(new WineVarietal(Varietal.SYRAH, syrah));
		frCat.addVarietal(new WineVarietal(Varietal.CABERNET_SAUVIGNON, cabernet_sauvignon));
		frCat.addVarietal(new WineVarietal(Varietal.MALBEC, malbec));
		frCat.addVarietal(new WineVarietal(Varietal.AGLIANICO, aglianico));
		frCat.addVarietal(new WineVarietal(Varietal.BARBERA, barbera));
		categories.add(frCat);
		
		
	}
}

